home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
video
/
zapem-0.000
/
zapem-0
/
zapem
/
main.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-06
|
15KB
|
678 lines
/* Copyright Alex Hornby 1994/1995. All rights reserved.
See file README for details
*/
extern "C"{
#include <stdio.h>
#include <stdlib.h>
#include <vga.h>
#include <vgakeyboard.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "btypes.h"
#include "gamelib.h"
#include "screendefs.h"
#include "soundIt.h"
#include "alopen.h"
}
// Include header files. Ordering does matter as my SE tutor says that modules
// should not include things without you knowing. ( speeds up compile times as
// well :)
#include "rnd.h"
#include "effects.h"
#include <iostream.h>
#include <string.h>
#include "palette.h"
#include "gif.h"
#include "asmblock.h"
#include "sprite.h"
#include "soul.h"
#include "entity.h"
#include "weapon.h"
#include "control.h"
#include "block.h"
#include "menu.h"
#include "slots.h"
#include "player.h"
#include "display.h"
// Weapon includes
#include "projectile.h"
#include "popgun.h"
#include "font.h"
#include "starfield.h"
// Control includes
#ifdef JOYSTICK
#include "Joystick.h"
#endif
#include "RawKey.h"
#include "Keyboard.h"
#define NUMBOMB 5
#define NUMALIEN 20
Palette gamepal;
animList explode;
StarField starfield;
Player ship;
Sprite bomb[NUMBOMB],alien[NUMALIEN],multiple,logo, checkerboard,life[NUMLIVES];
byte *vscreen;
Sample snd[NUM_SAMPLES];
bool aliendead[NUMALIEN];
bool option_effects=true;
int ticks, aliens_left, level;
int sred[256], sgreen[256], sblue[256];
Popgun pop(&ship);
/////////////////////////////////////////////////////////////////////////////
// Sets up the title screen
/////////////////////////////////////////////////////////////////////////////
void
primetitle(void)
{
cls(vscreen,0);
logo.setPos((logo.getScreenWidth()-logo.getWidth())/2,0);
logo.setVisible(true);
multiple.setPos(150,180);
multiple.setVisible(true);
}
////////////////////////////////////////////////////////////////////////////
// Sets the control to joystick if possible, or keyboard otherwise.
////////////////////////////////////////////////////////////////////////////
#ifdef JOYSTICK
Joystick joystick;
#endif
Control *set_joystick(Control *c)
{
if (c!=0 && c->getRaw()==true)
delete c;
#ifdef JOYSTICK
c=&joystick;
if (c->getOkay()==false)
{
c=new RawKey;
cerr << "Using Raw Keyboard\n";
}
#else
c=new RawKey;
cerr << "Using Raw Keyboard\n";
#endif
if(c->getOkay()==false)
{
cerr << "No controls available!" << endl;
}
return c;
}
Control* set_keyboard(Control *c)
{
if (c!=0 && c->getRaw()==true)
delete c;
c=new RawKey;
return c;
}
/////////////////////////////////////////////////////////////////////////////
// Main entry point - Also contains menu code (may change that!)
/////////////////////////////////////////////////////////////////////////////
int
main(void)
{
void initialise(void);
void getsprites(void);
void maingame( void);
int choice=0;
initialise();
cerr << "inited" << endl;
// Set the start up control
Control *control=0;
control=set_joystick(control);
ship.setControl(control);
cerr << "set slot" << endl;
ship.setWeapon(&pop,FRONT);
starfield.setGraphMem(vscreen);
getsprites();
cerr << "Got sprites" << endl;
gamepal.allocate(255, 30, 0, 0 );
gamepal.allocate(0, 0, 0, 0 );
char* menu1[]={"New Game", "Options","Load Game", "Save Game", "Quit"};
char* menu2[]={"Sound","Control"};
char* menu3[]={"On","Off"};
char* menu4[]={"Keyboard","Joystick"};
char** mtext[]={menu1,menu2,menu3,menu4};
int mlen[]={5,2,2,2};
int cmenu=0, oldcmenu=0;
Menu *menu;
menu=new Menu (mtext[cmenu],mlen[cmenu]);
menu->setControl(control);
use_palette(gamepal);
primetitle();
cerr << "Starting Loop" << endl;
while(choice!=4)
{
choice=menu->choice();
switch(cmenu)
{
case 0:
switch(choice)
{
case 0:
logo.hideAll();
maingame();
primetitle();
break;
case 1:
cmenu=1;
break;
default:
break;
}
break;
case 1:
switch(choice)
{
case 0:
cmenu=2;
break;
case 1:
cmenu=3;
break;
}
break;
case 2:
switch(choice)
{
case 0:
option_effects=true;
cmenu=0;
break;
case 1:
option_effects=false;
cmenu=0;
break;
}
break;
case 3:
switch(choice)
{
case 0:
control=set_keyboard(control);
cmenu=0;
break;
case 1:
control=set_joystick(control);
cmenu=0;
break;
}
menu->setControl(control);
ship.setControl(control);
break;
default:
break;
}
//cerr << "Moving" << endl;
starfield.move();
menu->move();
//cerr << "Moved" << endl;
starfield.getBack();
logo.getAll();
menu->getBack();
//cerr << "Got" << endl;
starfield.paste();
logo.PasteAll();
if(oldcmenu==cmenu)
menu->paste();
//cerr << "Displaying screen" << endl;
display(vscreen);
//cerr << "Displayed screen" << endl;
starfield.replace();
logo.ReplaceAll();
menu->replace();
if(oldcmenu!=cmenu)
{
delete menu;
menu=new Menu (mtext[cmenu],mlen[cmenu]);
while(control->test(FIRE1))
control->fetch();
menu->setControl(control);
}
oldcmenu=cmenu;
}
delete control;
exit(0);
}
/////////////////////////////////////////////////////////////////////////////
// Called at an exit() to tidy things up a bit
/////////////////////////////////////////////////////////////////////////////
void cleanup(void)
{
/* Back to boring text mode! */
cls(vga_getgraphmem(),0);
for(int i=0;i<256;i++)
vga_setpalette(i, sred[i], sgreen[i], sblue[i]);
vga_setmode(TEXT);
#ifdef SOUND
Snd_restore();
#endif
}
/////////////////////////////////////////////////////////////////////////////
// Sets up the graphics, fonts and sound
/////////////////////////////////////////////////////////////////////////////
void
initialise (void)
{
void cleanup(void);
/* Set up screen mode */
vga_init();
vga_setmode(G320x200x256);
/* Save palette */
for(int i=0;i<256;i++)
vga_getpalette(i, &sred[i], &sgreen[i], &sblue[i]);
/* Get font */
fontinit();
#ifdef SOUND
/* First, we load our raw samples into memory */
Snd_loadRawSample( "sfx/zap.raw", &snd[SND_POPGUN] );
Snd_loadRawSample( "sfx/explode.raw", &snd[SND_EXPLODE] );
Snd_loadRawSample( "sfx/harp.snd", &snd[SND_HARP] );
/* now init the soundIt library */
if (Snd_init( NUM_SAMPLES, snd, SAMPLE_RATE, NUM_CHANNELS, "/dev/dsp" )==EXIT_FAILURE)
{
printf("Can't init soundIt library. yech..\n");
exit(0);
}
#endif
/* Try to organise a tidy cleanup */
atexit(cleanup);
}
/////////////////////////////////////////////////////////////////////////////
// Cuts out the sprite images contained in the invsprit.gif file
/////////////////////////////////////////////////////////////////////////////
void
getsprites (void)
{
Gif gif;
Palette gifpal;
int i;
/* Load picture containing sprites */
FILE *fp=alopen("gfx/invsprit.gif","rb");
gif.Load(fp);
gifpal.scan(gif.getPtr(), gif.getWidth()*gif.getHeight());
gif.SetPalette(gifpal);
gamepal.remap(gif.getPtr(), gif.getWidth()*gif.getHeight() , gifpal);
ship.setGraphMem(gif.getPtr());
ship.Cut(8,16,4,8,POPGUNSLOT);
ship.Cut(0,16,8,16,PLASMAGUNSLOT);
pop.setSlot(POPGUNSLOT);
animList manim;
for(i=0;i<16;i++)
{
multiple.Cut(24+i*8,16,8,8,MULTSLOT+i);
manim.append(animElt(MULTSLOT+i,2));
}
manim.append(animElt(LOOPANIM,0));
multiple.loadFilm(manim);
multiple.setAnim(true);
/* Cut the sprites */
life[0].Cut(0,80,8,8,LIFESLOT);
for(i=1;i<NUMLIVES;i++)
life[i]=life[0];
logo.Cut(0,88,88,24,LOGOSLOT);
ship.Cut(0,0,16,16,SHIPSLOT);
ship.Cut(16,0,16,16,SHIPSLOT+1);
ship.Cut(32,0,16,16,SHIPSLOT+2);
ship.Cut(48,0,16,16,SHIPSLOT+3);
ship.Cut(64,0,16,16,SHIPSLOT+4);
ship.Cut(80,0,16,16,SHIPSLOT+5);
bomb[0].Cut(16,16,8,8,BOMBSLOT);
for(i=1;i<NUMBOMB;i++)
bomb[i]=bomb[0];
alien[0].Cut(0,32,16,16,EXPLODESLOT);
alien[0].Cut(16,32,16,16,EXPLODESLOT+1);
alien[0].Cut(32,32,16,16,EXPLODESLOT+2);
explode=animElt(EXPLODESLOT,2)+
animElt(EXPLODESLOT+1,2)+animElt(EXPLODESLOT+2,1)+animElt(VANISHANIM,0);
alien[0].Cut(48,48,16,16,ALIENSLOT);
alien[0].Cut(48,48,16,16,ALIENSLOT+1);
alien[0].Cut(48,48,16,16,ALIENSLOT+2);
vscreen=new byte [65535];
ship.setGraphMem(vscreen);
}
/////////////////////////////////////////////////////////////////////////////
// Puts the sprites in place at the start of a level
/////////////////////////////////////////////////////////////////////////////
void primesprites(void)
{
animList aan=animElt(ALIENSLOT,5) + animElt(ALIENSLOT+1,5)+ animElt(ALIENSLOT+2,5) + animElt(LOOPANIM,0);
alien[0].loadFilm(aan);
alien[0].setAnim(true);
for(int i=0;i<NUMALIEN;i++)
{
alien[i]=alien[0];
aliendead[i]=false;
}
ship.setPos(152,182);
for(i=0;i<ship.getLives();i++)
{
life[i].setPos(SCREENWIDTH-(i+1)*9,192);
}
i=0;
for(int y=0; y<NUMALIEN/5; y++)
{
for(int x=0; x<NUMALIEN/4; x++)
{
alien[i].setPos(x*40+100,y*30+20);
alien[i].setDelta(-1,0);
i++;
}
}
ship.setVisible(true);
for(i=0;i<ship.getLives();i++)
life[i].setVisible(true);
for(i=0;i<NUMALIEN;i++)
alien[i].setVisible(true);
}
/////////////////////////////////////////////////////////////////////////////
// Has the player collided with and alien?
/////////////////////////////////////////////////////////////////////////////
bool collide(void)
{
for(int a=0; a<NUMALIEN; a++)
{
if( alien[a].getVisible()==true && ship.collide(alien[a]) )
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////////////
// Checks if the player has shot anything.
/////////////////////////////////////////////////////////////////////////////
void checklaser(void)
{
for(int a=0; a<NUMALIEN; a++)
{
if( !aliendead[a] && ship.hit(alien[a]) )
{
aliens_left--;
alien[a].loadFilm(explode);
alien[a].setAnim(true);
aliendead[a]=true;
if(option_effects)
Snd_effect(SND_EXPLODE,CHAN_EXPLODE);
ship.addScore(10);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Checks if the aliens weapons have hit the player.
/////////////////////////////////////////////////////////////////////////////
void checkbomb(void)
{
for(int i=0;i<NUMBOMB;i++)
{
if(bomb[i].getVisible() && bomb[i].collide(ship))
{
ship.explode();
int oldlife=ship.getLives();
ship.subEnergy(20);
if(ship.getLives()<oldlife);
life[oldlife-1].disappear();
bomb[i].disappear();
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Moves the aliens bombs.
/////////////////////////////////////////////////////////////////////////////
void movebomb(void)
{
for(int i=0;i<NUMBOMB;i++)
{
bomb[i].move();
if(bomb[i].getYp()> SCREENHEIGHT-bomb[i].getHeight() )
bomb[i].disappear();
}
}
/////////////////////////////////////////////////////////////////////////////
// Launches and alien weapon
/////////////////////////////////////////////////////////////////////////////
void
alienfire( const Sprite& a)
{
static int last;
if(ticks-last>8)
{
int i=0;
while(bomb[i].getVisible() && i<NUMBOMB)
i++;
if(bomb[i].getVisible() || i>=NUMBOMB)
return;
bomb[i].setDelta(0, 1+level/2);
bomb[i].setPos(a.getXp()+4, a.getYp()+16);
bomb[i].appear();
last=ticks;
}
}
/////////////////////////////////////////////////////////////////////////////
// Moves the aliens.
/////////////////////////////////////////////////////////////////////////////
void movealiens(void)
{
int left=0, right=0, curalien;
/* move the aliens */
for(curalien=0; curalien<NUMALIEN; curalien++)
{
if(alien[curalien].getVisible())
{
if( alien[curalien].getXp() <= 0 )
right=1;
if( alien[curalien].getXp() > 303 )
left=1;
}
}
if(left)
{
for(curalien=0; curalien<NUMALIEN; curalien++)
{
alien[curalien].setDelta(-1,0);
alien[curalien].move(0,1+level);
}
}
if(right)
{
for(curalien=0; curalien<NUMALIEN; curalien++)
{
alien[curalien].setDelta(1,0);
alien[curalien].move(0,1+level);
}
}
for(curalien=0; curalien<NUMALIEN; curalien++)
{
alien[curalien].move();
if(!aliendead[curalien] && alien[curalien].getVisible() &&
(alien[curalien].getXp()==ship.getXp() || rnd(100)>80) )
alienfire(alien[curalien]);
}
}
/////////////////////////////////////////////////////////////////////////////
// Does the scrolling text ( Level one etc )
/////////////////////////////////////////////////////////////////////////////
void scrolly( char *message)
{
int x;
cls(vscreen,0);
for(x=0;x<SCREENWIDTH-strlen(message)*8;x+=2)
{
print(message,vscreen,x,SCREENHEIGHT/2-4);
waitvbl();
screencopy(vscreen,graph_mem);
}
cls(vscreen,0);
}
void levelintro(int l)
{
char buffer[80];
sprintf(buffer," Level %d",l);
scrolly(buffer);
}
/////////////////////////////////////////////////////////////////////////////
// Runs the high level game, ie sets up each level
/////////////////////////////////////////////////////////////////////////////
void maingame(void)
{
void gameinit(void);
void game(void);
level=1;
gameinit();
while(level<11 && ship.getLives()>0)
{
cls(vscreen,0);
starfield.getBack();
ship.hideAll();
primesprites();
if(option_effects)
Snd_effect(SND_HARP,CHAN_PLAYER);
levelintro(level);
for(int i=0;i<NUMALIEN;i++)
aliendead[i]=false;
game();
level++;
}
if(ship.getLives()==0)
scrolly(" You're dead, loser!.");
else if(level==11 && ship.getLives()>0)
scrolly(" You Won! Now code some more.");
ship.hideAll();
cls(vscreen,0);
}
void gameinit(void)
{
ship.setScore(0);
ship.setLives(3);
level=1;
}
/////////////////////////////////////////////////////////////////////////////
// The main game loop is in here.
/////////////////////////////////////////////////////////////////////////////
void game(void)
{
int key=0;
char buffer[80];
aliens_left=NUMALIEN;
Block panel;
panel.cut(0,192,80,8);
while(key!='q')
{
/* move the player */
ship.control();
/* move the aliens */
if(ticks%2) movealiens();
/*move the bullets*/
movebomb();
/*check bullets*/
checklaser();
checkbomb();
/*Check for a win*/
if(aliens_left<=0)
{
key='q';
}
/*check if the player is dead*/
if(collide() || ship.getLives()==0)
return;
/*************** Screen is updated here *********************/
/* First replace the background */
/* Then get the new background */
ship.getAll();
starfield.getBack();
panel.reCut(0,192);
/* Then paste on the graphics */
starfield.paste();
ship.PasteAll();
sprintf(buffer,"%d",ship.getScore());
printor(buffer, vscreen,0,192);
display(vscreen);
ship.ReplaceAll();
starfield.replace();
panel.paste(0,192);
starfield.move();
/*************** Count game ticks **************************/
ticks++;
}
}